/**
 * Copyright (c) 2017-2024 Nop Platform. All rights reserved.
 * Author: canonical_entropy@163.com
 * Blog:   https://www.zhihu.com/people/canonical-entropy
 * Gitee:  https://gitee.com/canonical-entropy/nop-entropy
 * Github: https://github.com/entropy-cloud/nop-entropy
 */
package com.gitee.wsl.struct.table.tree

import com.gitee.wsl.struct.table.CellPosition
import com.gitee.wsl.struct.table.ICell
import com.gitee.wsl.struct.table.ITableView
import com.gitee.wsl.struct.table.ProcessResult
import com.gitee.wsl.struct.table.impl.BaseTable


object TreeTableHelper {
    /**
     * 解析表格中的一个区域为TreeTable结构。
     */
    fun buildTreeTable(
        table: ITableView,
        beginRowIndex: Int, beginColIndex: Int,
        endRowIndex: Int, endColIndex: Int,
        vertical: Boolean
    ): BaseTable {
        val ret: BaseTable = BaseTable()
        for (i in beginRowIndex until endRowIndex) {
            val row = table.getRow(i)
                ?: throw IllegalArgumentException("ERR_TABLE_NULL_ROW")
                   /* .param(ARG_ROW_INDEX, i)*/

            row.forEachCell<ICell>(i) { cell, r, c ->
                if (c < beginColIndex) return@forEachCell ProcessResult.CONTINUE
                if (c >= endColIndex) return@forEachCell ProcessResult.STOP

                if (cell != null && cell.isProxyCell) {
                    return@forEachCell ProcessResult.CONTINUE
                }

                val retCell = TreeCell(
                    cell,
                    if (vertical) TreeCellChildPosition.bottom_hor else TreeCellChildPosition.right_ver
                )
                retCell.rowIndex = r - beginRowIndex
                retCell.colIndex = c - beginColIndex
                retCell.id = CellPosition.toABString(r, c)
                retCell.value = cell

                if (cell != null) {
                    retCell.mergeAcross = cell.mergeAcross
                    retCell.mergeDown = cell.mergeDown
                    retCell.comment = cell.comment
                }
                ret.setCell(retCell.rowIndex, retCell.colIndex, retCell)
                ProcessResult.CONTINUE
            }
        }

        buildParentChildren(ret, vertical)
        return ret
    }

    private fun buildParentChildren(table: ITableView, vertical: Boolean) {
        if (vertical) {
            val rowCount: Int = table.rowCount
            val row = table.getRow(rowCount - 1)?:return
            var leafIndex = 0
            var i = 0
            val n: Int = table.rowCount
            while (i < n) {
                val cell= row.getCell(i)!!.realCell as TreeCell
                buildParentChildren(table, cell, true)
                i += cell.mergeAcross
                cell.leafIndex = leafIndex++
                i++
            }
        } else {
            val colCount: Int = table.colCount
            var leafIndex = 0
            var i = 0
            val n: Int = table.rowCount
            while (i < n) {
                val cell = table.getCell(i, colCount - 1)!!.realCell as TreeCell
                buildParentChildren(table, cell, false)
                i += cell.mergeDown
                cell.leafIndex = leafIndex++
                i++
            }
        }
    }

    private fun buildParentChildren(table: ITableView, cell: TreeCell, vertical: Boolean) {
        if (cell.parent != null) return

        if (vertical) {
            if (cell.rowIndex == 0) return

            val prevCell: TreeCell =
                table.getCell(cell.rowIndex - 1, cell.colIndex)!!.realCell as TreeCell
            if (prevCell.colIndex > cell.colIndex
                || prevCell.endColIndex < cell.endColIndex
            ) throw IllegalArgumentException("ERR_TABLE_NOT_TREE_CELL")
               /* .param(ARG_CELL_POS, cell.id)*/

            prevCell.addChild(cell)
            buildParentChildren(table, prevCell, true)

            cell.treeLevel = prevCell.treeLevel + 1
        } else {
            if (cell.colIndex == 0) return

            val prevCell: TreeCell =
                table.getCell(cell.rowIndex, cell.colIndex - 1)!!.realCell as TreeCell
            if (prevCell.rowIndex > cell.rowIndex
                || prevCell.endRowIndex < cell.endRowIndex
            ) throw IllegalArgumentException("ERR_TABLE_NOT_TREE_CELL")
               /* .param(ARG_CELL_POS, cell.id)*/

            prevCell.addChild(cell)

            buildParentChildren(table, prevCell, false)

            cell.treeLevel = prevCell.treeLevel + 1
        }
    }
}
